package sample;

import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Optional;

public class Alerts {

    private static final Logger LOGGER = LoggerFactory.getLogger(Alerts.class);

    private String title;
    private String headerText;
    private String contentText;
    private Node dialogPane;

    private Alerts(){}

    public Alerts title(String title) {
        this.title = title;
        return this;
    }

    public Alerts headerText(String headerText) {
        this.headerText = headerText;
        return this;
    }

    public Alerts contentText(String contentText) {
        this.contentText = contentText;
        return this;
    }

    public Alerts dialogPane(Node dialogPane) {
        this.dialogPane = dialogPane;
        return this;
    }

    public static Alerts create(){
        return new Alerts();
    }

    private void basic(Alert alert, String defaultTitle) {
        alert.setTitle(Optional.ofNullable(this.title).orElse(defaultTitle));
        Optional.ofNullable(this.headerText).ifPresent(alert::setHeaderText);
        Optional.ofNullable(this.contentText).ifPresent(alert::setContentText);
        Optional.ofNullable(this.dialogPane).ifPresent(p->alert.getDialogPane().setContent(p));

        LOGGER.info("show dialog title:{},headerText:{},contentText:{}",title,headerText,contentText);
    }

    public Optional<ButtonType> showInformation(){
        Alert alert = new Alert(AlertType.INFORMATION);
        basic(alert, "提示");

        return alert.showAndWait();
    }

    public Optional<ButtonType> showWarning(){
        Alert alert = new Alert(AlertType.WARNING);
        basic(alert, "警告");

        return alert.showAndWait();
    }

    public Optional<ButtonType> showError() {
        Alert alert = new Alert(AlertType.ERROR);
        basic(alert, "错误");

        return alert.showAndWait();
    }

    public void showException(Exception ex) {
        Alert alert = new Alert(AlertType.ERROR);
        basic(alert, "异常");

        // Create expandable Exception.
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        String exceptionText = sw.toString();

        Label label = new Label("The exception stacktrace was:");

        TextArea textArea = new TextArea(exceptionText);
        textArea.setEditable(false);
        textArea.setWrapText(true);

        textArea.setMaxWidth(Double.MAX_VALUE);
        textArea.setMaxHeight(Double.MAX_VALUE);
        GridPane.setVgrow(textArea, Priority.ALWAYS);
        GridPane.setHgrow(textArea, Priority.ALWAYS);

        GridPane expContent = new GridPane();
        expContent.setMaxWidth(Double.MAX_VALUE);
        expContent.add(label, 0, 0);
        expContent.add(textArea, 0, 1);

        // Set expandable Exception into the dialog pane.
        alert.getDialogPane().setExpandableContent(expContent);

        alert.showAndWait();
    }

    public Optional<ButtonType> showConfirmation() {
        Alert alert = new Alert(AlertType.CONFIRMATION);
        basic(alert, "确认");

        return alert.showAndWait();
    }

    public Optional<ButtonType> showConfirmation(ButtonType... buttonTypes){
        Alert alert = new Alert(AlertType.CONFIRMATION);
        basic(alert, "确认");

        alert.getButtonTypes().setAll(buttonTypes);

        return alert.showAndWait();
    }

    public Optional<Pair<String, String>> showLogin(){
        // Create the custom dialog.
        Dialog<Pair<String, String>> dialog = new Dialog<>();
        dialog.setTitle(Optional.ofNullable(title).orElse("登录"));
        dialog.setHeaderText("Look, a Custom Login Dialog");

        // Set the icon (must be included in the project).
        dialog.setGraphic(new ImageView("/img/login.png"));

        // Set the button types.
        ButtonType loginButtonType = new ButtonType("登录", ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);

        // Create the username and password labels and fields.
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        TextField username = new TextField();
        username.setPromptText("用户名");
        PasswordField password = new PasswordField();
        password.setPromptText("密码");

        grid.add(new Label("用户名:"), 0, 0);
        grid.add(username, 1, 0);
        grid.add(new Label("密码:"), 0, 1);
        grid.add(password, 1, 1);

        // Enable/Disable login button depending on whether a username was entered.
        Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
        loginButton.setDisable(true);

        // Do some validation (using the Java 8 lambda syntax).
        username.textProperty().addListener((observable, oldValue, newValue) -> {
            loginButton.setDisable(newValue.trim().isEmpty());
        });

        dialog.getDialogPane().setContent(grid);

        // Request focus on the username field by default.
        Platform.runLater(username::requestFocus);

        // Convert the result to a username-password-pair when the login button is clicked.
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == loginButtonType) {
                return new Pair<>(username.getText(), password.getText());
            }
            return null;
        });

        return dialog.showAndWait();
    }
}
